/*
 * Copyright 2018-9-30 20:11:44 The JA-SIG Collaborative. All rights reserved.
 * distributed with thi file and available online at
 */
package com.lap.scp.erp.ao.impl;

import java.util.List;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.validation.BindingResult;

import com.lap.scd.commons.ao.AbstractAO;
import com.lap.scd.commons.constant.RespCode;
import com.lap.scd.commons.core.exception.ManagerException;
import com.lap.scd.commons.page.Page;
import com.lap.scd.commons.page.PageResult;
import com.lap.scd.commons.page.PageUtils;
import com.lap.scd.commons.result.Resp;
import com.lap.scp.erp.ao.ReceivablesAO;
import com.lap.scp.erp.core.ContractManager;
import com.lap.scp.erp.core.ReceivablesManager;
import com.lap.scp.erp.domain.ContractDO;
import com.lap.scp.erp.domain.ReceivablesDO;
import com.lap.scp.erp.query.ReceivablesQueryVO;

/**
 * <pre>
 *   默认 收款信息，记录合同的收款信息，可以有多条记录，并记录每个阶段的金额应用实现类，提供收款信息，记录合同的收款信息，可以有多条记录，并记录每个阶段的金额相关的流程应用操作、查询等。
 *
 * </pre>
 * 
 * @author 劳水生 Exp
 * @Date 2018-9-30 20:11:44
 * @since 2.0.0
 */
@Service("receivablesAO")
public class DefaultReceivablesAO extends AbstractAO implements ReceivablesAO {
	/**
	 * 收款信息，记录合同的收款信息，可以有多条记录，并记录每个阶段的金额业务操作对象
	 */
	@Resource
	private ReceivablesManager receivablesManager;
	/**
	 * 合同业务管理对象
	 */
	@Resource
	private ContractManager contractManager;

	@Override
	public Resp<ReceivablesDO> insertReceivables(ReceivablesDO receivablesDO, BindingResult errors) {
		Resp<ReceivablesDO> resp = new Resp<>();
		try {
			this.validate(resp, receivablesDO);
			this.validateAdd(resp, receivablesDO);
			if (resp.isSuccess()) {
				receivablesManager.insertReceivables(receivablesDO);
				resp.setData(receivablesDO);
			}
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(receivablesDO, e);
		}
		return resp;
	}

	/**
	 * 简单的非法数据校验
	 * 
	 * @param resp
	 * @param receivablesDO
	 */
	private void validate(Resp<?> resp, ReceivablesDO receivablesDO) {
		if (receivablesDO == null) {
			resp.putMsg(getMsg("301"));
		} else {
			Integer totalAmount = receivablesDO.getTotalAmount();
			Integer receivedAmount = receivablesDO.getReceivedAmount();
			if (totalAmount == null || totalAmount.intValue() < 0) {
				resp.putMsg(getMsg("302"));
			}
			if (receivedAmount == null || receivedAmount.intValue() < 0) {
				resp.putMsg(getMsg("303"));
			}
			if (receivablesDO.getPeriods() == null || receivablesDO.getPeriods() <= 0) {
				resp.putMsg(getMsg("305"));
			}
			if (resp.isSuccess()) {
				if (receivedAmount.intValue() > totalAmount.intValue()) {
					resp.putMsg(getMsg("307"));
				}
			}
		}
	}

	/**
	 * 业务校验，主要校验占比是否已经超过100
	 * 
	 * @param resp
	 * @param receivablesDO
	 * @throws ManagerException
	 */
	private void validateAdd(Resp<?> resp, ReceivablesDO receivablesDO) throws ManagerException {
		ContractDO contractDO = contractManager.queryById(receivablesDO.getContractId());
		if (contractDO == null) {
			resp.putMsg(getMsg("401"));
			return;
		}
		List<ReceivablesDO> list = receivablesManager.queryByContractId(receivablesDO.getContractId());
		if (list != null) {
			int totalAmount = 0;
			for (ReceivablesDO queryDO : list) {
				if (queryDO.getTotalAmount() != null) {
					totalAmount = totalAmount + queryDO.getTotalAmount();
				}
			}
			totalAmount = totalAmount + receivablesDO.getTotalAmount();
			if (totalAmount > contractDO.getTotalAmount().intValue()) {
				resp.putMsg(getMsg("306"));
			}
		}
	}

	@Override
	public Resp<Integer> deleteById(Integer receivablesId) {
		Resp<Integer> resp = new Resp<>();
		try {
			int flag = receivablesManager.deleteById(receivablesId);
			resp.setData(flag);
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(receivablesId, e);
		}
		return resp;
	}

	@Override
	public Resp<ReceivablesDO> queryById(Integer receivablesId) {
		Resp<ReceivablesDO> model = new Resp<>();
		try {
			ReceivablesDO receivablesDO = receivablesManager.queryById(receivablesId);
			model.setData(receivablesDO);
		} catch (Exception e) {
			model.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(receivablesId, e);
		}
		return model;
	}

	@Override
	public PageResult<ReceivablesDO> queryPage(Page page, ReceivablesQueryVO queryVO) {
		PageResult<ReceivablesDO> pr = new PageResult<>();
		try {
			List<ReceivablesDO> list = receivablesManager.queryPage(page, queryVO);

			PageUtils.copyPage(pr, page);
			pr.setData(list);
		} catch (Exception e) {
			pr.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(new Object[] { page, queryVO }, e);
		}
		return pr;
	}

	@Override
	public Resp<Integer> updateReceivables(ReceivablesDO receivablesDO) {
		Resp<Integer> resp = new Resp<>();
		try {
			this.validate(resp, receivablesDO);
			this.validateUpdate(resp, receivablesDO);
			if (resp.isSuccess()) {
				int flag = receivablesManager.updateReceivables(receivablesDO);
				resp.setData(flag);
			}
		} catch (Exception e) {
			resp.putMsg(RespCode.Error, super.getMsg("505", new String[] { e.getLocalizedMessage() }));
			super.writeLog(receivablesDO, e);
		}
		return resp;
	}

	/**
	 * 业务校验，主要校验占比是否已经超过100
	 * 
	 * @param resp
	 * @param receivablesDO
	 * @throws ManagerException
	 */
	private void validateUpdate(Resp<?> resp, ReceivablesDO receivablesDO) throws ManagerException {
		ContractDO contractDO = contractManager.queryById(receivablesDO.getContractId());
		if (contractDO == null) {
			resp.putMsg(getMsg("401"));
			return;
		}
		List<ReceivablesDO> list = receivablesManager.queryByContractId(receivablesDO.getContractId());
		if (list != null) {
			int totalRate = 0;
			for (ReceivablesDO queryDO : list) {
				if (queryDO.getTotalAmount() != null && queryDO.getId() != receivablesDO.getId()) {
					totalRate = totalRate + queryDO.getTotalAmount();
				}
			}
			totalRate = totalRate + receivablesDO.getTotalAmount();
			if (totalRate > contractDO.getTotalAmount().intValue()) {
				resp.putMsg(getMsg("306"));
			}
		}
	}

}
